@page "/call-todo-web-api-csr"
@rendermode InteractiveWebAssembly
@using BlazorApp.Client.Models
@implements IDisposable
@inject PersistentComponentState ApplicationState
@inject IConfiguration Config
@inject HttpClient Http

<PageTitle>Call Todo web API (CSR)</PageTitle>

<h1>Call Todo web API Example (CSR)</h1>

@if (todoItems == null)
{
    <p>No Todo Items found.</p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th class="text-center">
                    <label>
                        Complete
                        <input type="checkbox" @bind="getCompletedItems" @bind:after="GetTodoItems" />
                    </label>
                </th>
                <th>Name</th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            <tr id="editRow" style="display:@editRowStyle">
                <td class="text-center">
                    <input type="checkbox" @bind="editItem.IsComplete" />
                </td>
                <td>
                    <input @bind="editItem.Name" />
                </td>
                <td class="text-center">
                    <button class="btn btn-success" @onclick="SaveItem">
                        Save
                    </button>
                    <button class="btn btn-danger" 
                            @onclick="@(() => editRowStyle = "none")">
                        Cancel
                    </button>
                </td>
            </tr>
            @foreach (var item in todoItems)
            {
                <tr>
                    <td class="text-center">
                        @if (item.IsComplete)
                        {
                            <span>✔</span>
                        }
                    </td>
                    <td>@item.Name</td>
                    <td class="text-center">
                        <button class="btn btn-warning" @onclick="@(() => EditItem(item.Id))">
                            Edit
                        </button>
                        <button class="btn btn-danger" @onclick="@(async () => await DeleteItem(item.Id))">
                            Delete
                        </button>
                    </td>
                </tr>
            }
            <tr id="addRow">
                <td></td>
                <td>
                    <input @bind="newItemName" placeholder="New Todo Item" />
                </td>
                <td class="text-center">
                    <button class="btn btn-success" @onclick="AddItem">Add</button>
                </td>
            </tr>
        </tbody>
    </table>
}

@code {
    private TodoItem editItem = new();
    private string editRowStyle = "none";
    private string? newItemName;
    private string? serviceEndpoint;
    private TodoItem[]? todoItems;
    private bool getCompletedItems;
    private PersistingComponentStateSubscription persistingSubscription;

    protected override async Task OnInitializedAsync()
    {
        serviceEndpoint = $"{Config.GetValue<string>("BackendUrl")}/todoitems";

        if (!ApplicationState.TryTakeFromJson<TodoItem[]>(nameof(todoItems), out var restoredData))
        {
            await GetTodoItems();
        }
        else
        {
            todoItems = restoredData!;
        }

        // Call at the end to avoid a potential race condition at app shutdown
        persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
    }

    private async Task GetTodoItems()
    {
        var requestUri = getCompletedItems ? $"{serviceEndpoint}/complete" : serviceEndpoint;
        todoItems = await Http.GetFromJsonAsync<TodoItem[]>(requestUri) ?? [];
    }

    private Task PersistData()
    {
        ApplicationState.PersistAsJson(nameof(todoItems), todoItems);

        return Task.CompletedTask;
    }

    private void EditItem(long id)
    {
        if (todoItems is not null)
        {
            editItem = todoItems.Single(i => i.Id == id);
            editRowStyle = "table-row";
        }
    }

    private async Task AddItem()
    {
        if (!string.IsNullOrEmpty(newItemName))
        {
            var addItem = new TodoItem { Name = newItemName, IsComplete = false };
            await Http.PostAsJsonAsync(serviceEndpoint, addItem);
            newItemName = string.Empty;
            await GetTodoItems();
            editRowStyle = "none";
        }
    }

    private async Task SaveItem()
    {
        if (editItem is not null)
        {
            await Http.PutAsJsonAsync($"{serviceEndpoint}/{editItem.Id}", editItem);
        }
        await GetTodoItems();
        editRowStyle = "none";
    }

    private async Task DeleteItem(long id)
    {
        await Http.DeleteAsync($"{serviceEndpoint}/{id}");
        await GetTodoItems();
        editRowStyle = "none";
    }

    void IDisposable.Dispose() => persistingSubscription.Dispose();
}
